package com.gopay.bis.nucc.common.impl;

import com.gopay.bis.nucc.common.util.NuccCertHelper;
import com.gopay.bis.nucc.common.util.NuccHttpClientUtil;
import com.gopay.common.cache.client.RedisClient;
import com.gopay.common.constants.bank.NuccConstants;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.domain.bank.BaseMessage;
import com.gopay.common.domain.bank.nucc.common.base.NuccBaseMessage;
import com.gopay.common.domain.bank.nucc.common.query.res.NuccQueryRes;
import com.gopay.common.domain.bank.nucc.common.refund.res.NuccRefundRes;
import com.gopay.common.domain.bank.nucc.common.serial.res.NuccSerialBodyCtrlnbinfLst;
import com.gopay.common.domain.bank.nucc.common.serial.res.NuccSerialRes;
import com.gopay.common.exception.GopayException;
import com.gopay.remote.bank.businesses.NuccCommonService;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 网联公共接口
 * Created by zhoutong on 2018/1/*/
public class NuccCommonServiceImpl implements NuccCommonService {

    /**
     * 日志
     */
    private static Logger logger = LoggerFactory.getLogger(NuccCommonServiceImpl.class);

    /**
     * 安全工具类
     */
    private NuccCertHelper nuccCertHelper;

    /**
     * 通讯工具类
     */
    private NuccHttpClientUtil nuccHttpClientUtil;

    @Override
    public Object queryTransStatus(BaseMessage baseMsg) throws GopayException {
        NuccBaseMessage message = (NuccBaseMessage) baseMsg;
        NuccQueryRes res;
        try{
            message = nuccCertHelper.sign(message);
            Map<String,String> map = new HashMap<>();
            map.put("MsgTp", message.getMsgHeader().getMsgTp());
            map.put("OriIssrId", message.getMsgHeader().getIssrId());
            String response = nuccHttpClientUtil.send(message.getPayUrl(), message.getPlainMessage()+message.getSignMessage(), map);
            res = (NuccQueryRes) nuccCertHelper.verify(response,  NuccQueryRes.class);
            if(res == null){
                logger.error("网联交易状态查询异常，返回跳转报文为空");
                throw new GopayException(ProcCodeConstants.PROC_CODE_100E6132);
            }
        }catch (GopayException e) {
            logger.error("网联交易状态查询异常" , e);
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6132,e);
        } catch (Exception ex) {
            logger.error("网联交易状态查询异常" , ex);
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6132,ex);
        }
        return res;
    }

    @Override
    public synchronized void serialApply(BaseMessage baseMsg) throws GopayException {
        NuccBaseMessage message =  (NuccBaseMessage)baseMsg;
        NuccSerialRes res;
        try{
            message = nuccCertHelper.sign(message);
            Map<String,String> map = new HashMap<>();
            map.put("MsgTp", message.getMsgHeader().getMsgTp());
            map.put("OriIssrId", message.getMsgHeader().getIssrId());
            String response = nuccHttpClientUtil.send(message.getPayUrl(), message.getPlainMessage()+message.getSignMessage(), map);
            res = (NuccSerialRes) nuccCertHelper.verify(response,  NuccSerialRes.class);
            if(res != null && NuccConstants.NUCC_SYSRTNCD_SUCCESS.equals(res.getMsgBody().getSysRtnInf().getSysRtnCd())){
                List<NuccSerialBodyCtrlnbinfLst> list = res.getMsgBody().getCtrlNbInf();
                if(list!= null && list.size()>0){
                    //按key清除之前的流水号缓存
                    RedisClient.del(NuccConstants.NUCC_SERIAL_REDIS_KEY);
                    int count = 0;
                    for(int i=0;i<list.size();i++){
                        NuccSerialBodyCtrlnbinfLst clb =list.get(i);
                        //控制位前2位
                        String ctrlNbF = clb.getCtrlNbF();
                        //控制位后4位
                        String[] ctrlNbLs = clb.getCtrlNbL().split("\\|");
                        for(int j=0;j<ctrlNbLs.length;j++){
                            String ctrlNbL = ctrlNbLs[j];
                            RedisClient.hset(NuccConstants.NUCC_SERIAL_REDIS_KEY, NuccConstants.NUCC_SERIAL_REDIS_FIELD +count++, ctrlNbF+ctrlNbL);
                        }
                    }
                }
            }else{
                throw new GopayException(ProcCodeConstants.PROC_CODE_100E6120);
            }
        }catch (GopayException e) {
            logger.error("网联流水号申请异常" , e);
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6120,e);
        } catch (Exception ex) {
            logger.error("网联流水号申请异常" , ex);
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6120,ex);
        }
    }

    @Override
    public Object refund(BaseMessage baseMsg) throws GopayException {
        NuccBaseMessage message = (NuccBaseMessage) baseMsg;
        NuccRefundRes res;
        try{
            message = nuccCertHelper.sign(message);
            Map<String,String> map = new HashMap<>();
            map.put("MsgTp", message.getMsgHeader().getMsgTp());
            map.put("OriIssrId", message.getMsgHeader().getIssrId());
            String response = nuccHttpClientUtil.send(message.getPayUrl(), message.getPlainMessage()+message.getSignMessage(), map);
            res = (NuccRefundRes) nuccCertHelper.verify(response,  NuccRefundRes.class);
            if(res == null){
                logger.error("网联退款请求异常，返回跳转报文为空");
                throw new GopayException(ProcCodeConstants.PROC_CODE_100E6133);
            }
        }catch (GopayException e) {
            logger.error("网联退款请求异常" , e);
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6133,e);
        } catch (Exception ex) {
            logger.error("网联退款请求异常" , ex);
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E6133,ex);
        }
        return res;
    }

    public NuccCertHelper getNuccCertHelper() {
        return nuccCertHelper;
    }

    public void setNuccCertHelper(NuccCertHelper nuccCertHelper) {
        this.nuccCertHelper = nuccCertHelper;
    }

    public NuccHttpClientUtil getNuccHttpClientUtil() {
        return nuccHttpClientUtil;
    }

    public void setNuccHttpClientUtil(NuccHttpClientUtil nuccHttpClientUtil) {
        this.nuccHttpClientUtil = nuccHttpClientUtil;
    }
}
